'use client';

import {
  Slider,
  SliderFilledTrack,
  SliderThumb,
  SliderTrack,
} from '@chakra-ui/react';
import clsx from 'clsx';
import { observer } from 'mobx-react-lite';
import { useSearchParams } from 'next/navigation';
import {
  useCallback,
  useEffect,
  useLayoutEffect,
  useRef,
  useState,
} from 'react';
import { twMerge } from 'tailwind-merge';
import { useIsClient } from 'usehooks-ts';

import { useStores } from '@/app/(root)/AppProviders';
import Button, {
  ButtonShape,
  ButtonSize,
  ButtonVariant,
} from '@/components/button/Button';
import ImageWithFallback from '@/components/image/ImageWithFallback';
import Logo from '@/components/image/Logo';
import Link from '@/components/link/Link';
import { formatDuration } from '@/components/song/songUtils';
import { LinkIcon, PauseIcon, PlayIcon, PulsingLinesIcon } from '@/icons';
import { Clip } from '@/state/clipStore';
import { getClipTitle } from '@/utils/clip';
import { colorVar } from '@/utils/utils';

const ThemedButton: React.FC<React.ComponentProps<typeof Button>> = (props) => (
  <Button
    {...props}
    variant={ButtonVariant.Inherit}
    className={twMerge(
      clsx({
        'bg-(--color-embed-button-bg) text-(--color-embed-button-fg)':
          !props.variant,
      }),
      props.className
    )}
  />
);

const PlaySlider = observer(() => {
  const stores = useStores();
  const playbarState = stores.playbar;

  const [tempProgress, setTempProgress] = useState<number | null>(null);
  return (
    <div className='flex w-full flex-row items-center justify-stretch'>
      <div className='text-xs text-(--color-embed-text-secondary)'>
        {formatDuration(playbarState.currentTime)}
      </div>
      {/* @TODO: Un-Chakra the slider */}
      <Slider
        isDisabled={playbarState.clip?.id == null}
        flex='1'
        mx={4}
        colorScheme='orange'
        aria-label='playtime'
        focusThumbOnChange={false}
        value={
          tempProgress != null ? tempProgress : playbarState.progress * 100
        }
        onChange={(value) => setTempProgress(value)}
        onChangeEnd={(value) => {
          playbarState.userSetCurrentProgress(value);
          setTempProgress(null);
        }}
      >
        <SliderTrack bg={colorVar('embed-slider-rail')}>
          <SliderFilledTrack bg={colorVar('embed-slider-progress')} />
        </SliderTrack>
        <SliderThumb
          bg={colorVar('embed-slider-thumb')}
          _disabled={{ bg: colorVar('embed-slider-thumb-disabled') }}
        />
      </Slider>
      <div className='text-xs text-(--color-embed-text-secondary)'>
        {formatDuration(playbarState.duration)}
      </div>
    </div>
  );
});

const SongEmbedClient = observer(({ clip }: { clip: Clip }) => {
  const { playbar, clips: clipsStore } = useStores();

  const searchParams = useSearchParams();
  const autoplay =
    searchParams.get('autoplay') === '1' ||
    searchParams.get('autoplay') === 'true';

  const audioRef = useRef<HTMLAudioElement>(null);

  useLayoutEffect(() => {
    if (audioRef.current) {
      playbar.setAudioElement(audioRef.current);
    }
  }, [playbar]);

  useEffect(() => {
    clipsStore.updateClips([clip]);
  }, [clipsStore, clip]);

  const handlePlayClick = useCallback(() => {
    if (playbar.clip?.id === clip.id) {
      playbar.togglePlay();
      return;
    }
    playbar.playClip(clip);
  }, [clip, playbar]);

  const isClient = useIsClient();

  const [isHovered, setIsHovered] = useState(false);
  const handleMouseEnter = useCallback(() => {
    setIsHovered(true);
  }, []);
  const handleMouseLeave = useCallback(() => {
    setIsHovered(false);
  }, []);

  const icon = !playbar.isPlaying ? (
    <PlayIcon className='h-5 w-5' />
  ) : isHovered ? (
    <PauseIcon className='h-5 w-5' />
  ) : (
    <PulsingLinesIcon className='-m-0.5 h-6 w-6' />
  );

  // Autoplay support
  useEffect(() => {
    if (autoplay && isClient) {
      const timeout = setTimeout(() => {
        if (playbar.clip?.id !== clip.id) {
          playbar.playClip(clip);
        }
      }, 1000);
      return () => {
        clearTimeout(timeout);
      };
    }
  }, [autoplay, isClient, playbar, clip]);

  // Card layout @media query, for convenience: max-xs:[@media(min-height:400px)]

  return (
    <div
      className={clsx(
        'relative h-full flex-1',
        'p-2 xs:[@media(min-height:144px)]:p-4 md:[@media(min-height:256px)]:p-8',
        'gap-2 xs:gap-4',
        'flex flex-row items-center justify-center',
        'bg-linear-to-b from-(--color-embed-bg-a) to-(--color-embed-bg-b)',
        // Card layout
        'max-xs:[@media(min-height:400px)]:flex-col max-xs:[@media(min-height:400px)]:items-stretch'
      )}
    >
      <div
        className={clsx(
          'mx-auto aspect-square',
          'max-h-[calc(100vh-1rem)] max-w-[50%]',
          '[@media(max-width:474px)_and_(max-height:150px)]:max-h-[calc((100vw*108/342)-1rem)]', // X workaround
          'xs:[@media(min-height:144px)]:max-h-[calc(100vh-2rem)]',
          'md:[@media(min-height:256px)]:max-h-[calc(100vh-4rem)]',
          'xs:h-36 sm:h-48 md:h-56',
          'max-2xs:[@media(max-height:240px)]:hidden',
          'max-xs:[@media(min-height:400px)]:max-h-[50vh]',
          'max-xs:[@media(min-height:400px)]:mt-auto'
        )}
      >
        <ImageWithFallback
          className={clsx(
            'aspect-square max-h-full w-full',
            'cursor-pointer rounded-md object-contain'
          )}
          alt='Song Image'
          src={clip.image_url || ''}
          onClick={handlePlayClick}
        />
      </div>
      <div className='flex flex-1 flex-col items-stretch justify-center gap-2 max-xs:[@media(min-height:400px)]:grow-0'>
        <h2 className='font-sans text-base font-bold text-ellipsis text-(--color-embed-text-primary) [@media(max-height:192px)]:line-clamp-2 [@media(max-width:474px)_and_(max-height:150px)]:line-clamp-1'>
          <Link href={`/song/${clip.id}/`} target='_blank'>
            {getClipTitle(clip)}
          </Link>
        </h2>
        <div className='flex flex-row items-center justify-stretch gap-4'>
          <ThemedButton
            size={ButtonSize.Large}
            shape={ButtonShape.Pill}
            aspectSquare
            icon={icon}
            onClick={handlePlayClick}
            onMouseEnter={handleMouseEnter}
            onMouseLeave={handleMouseLeave}
          />
          <PlaySlider />
          <audio ref={audioRef} preload='auto' src={clip.audio_url!} />
        </div>
      </div>
      <div
        className={clsx(
          'relative flex flex-col items-end justify-between self-stretch',
          'max-xs:[@media(min-height:400px)]:mt-auto max-xs:[@media(min-height:400px)]:flex-row'
        )}
      >
        <div
          className={clsx(
            'xs:[@media(max-height:160px)]:hidden',
            'max-xs:hidden',
            'absolute top-0 right-0',
            'sm:[@media(max-height:128px)]:relative'
          )}
        >
          <Button
            className='text-(--color-embed-text-primary) before:opacity-10 hover:before:opacity-25'
            variant={ButtonVariant.Inherit}
            size={ButtonSize.Medium}
            shape={ButtonShape.Rounded}
            icon={LinkIcon}
            target='_blank'
            href={`/song/${clip.id}/`}
            aria-label='Go to song'
          />
        </div>
        <div />
        <div
          className={clsx(
            'absolute right-0 bottom-0',
            'sm:[@media(max-height:160px)]:relative'
          )}
        >
          <Logo
            className={clsx(
              'block h-8 w-24',
              '[@media(max-height:160px)]:h-4 [@media(max-height:160px)]:w-12'
            )}
            target='_blank'
            href='/'
            aria-label='Go to Suno'
            color={colorVar('embed-text-primary')}
          />
        </div>
      </div>
    </div>
  );
});

export default SongEmbedClient;
